home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
comm2
/
termsorc.lha
/
Extras
/
Source
/
gtlayout-source.lha
/
LTP_PopupClass.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-26
|
26KB
|
1,180 lines
/* GadTools layout toolkit
**
** Copyright © 1993-1995 by Olaf `Olsen' Barthel
** Freely distributable.
**
** :ts=4
*/
#include "gtlayout_global.h"
//#define DB(x) x
#define DB(x) ;
#if defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
#define PIF_SingleActive (1 << 0)
#define PIF_ArrowUp (1 << 1)
#define PIF_ArrowDown (1 << 2)
/* // Intuition ghosts images all by itself
STATIC VOID __regargs
DrawDisabled(struct RastPort *RPort,UWORD Left,UWORD Top,UWORD Width,UWORD Height,UWORD *Pens)
{
SetAPen(RPort,Pens[BLOCKPEN]);
SetDrMd(RPort,JAM1);
SetAfPt(RPort,(UWORD *)&ghostingPat,1);
RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
SetAfPt(RPort,NULL,0);
}
*/
STATIC VOID __regargs
DrawArrow(struct RastPort *RPort,UWORD Left,UWORD Top,LONG ArrowWidth,LONG ArrowHeight,WORD Dir)
{
if(Dir < 0)
{
LONG i,Width,Start;
for(i = 0 ; i < ArrowHeight ; i++)
{
Width = ((ArrowWidth * (i + 1)) / ArrowHeight) & ~1;
if(Width < ArrowWidth)
Width++;
Start = Left + (ArrowWidth - Width) / 2;
Move(RPort,Start,Top + i);
Draw(RPort,Start + Width - 1,Top + i);
}
}
else
{
LONG i,Width,Start;
for(i = 0 ; i < ArrowHeight ; i++)
{
Width = ((ArrowWidth * (i + 1)) / ArrowHeight) & ~1;
if(Width < ArrowWidth)
Width++;
Start = Left + (ArrowWidth - Width) / 2;
Move(RPort,Start,Top + ArrowHeight - 1 - i);
Draw(RPort,Start + Width - 1,Top + ArrowHeight - 1 - i);
}
}
}
STATIC VOID __regargs
DrawContainer(struct RastPort *RPort,UWORD Left,UWORD Top,UWORD Width,UWORD Height,struct GadgetInfo *GadgetInfo,PopInfo *Info,BOOL Highlight,BOOL Disabled)
{
UWORD Shine,Shadow,Txt,Fill;
UWORD *Pens;
Pens = GadgetInfo->gi_DrInfo->dri_Pens;
if(Highlight)
{
Shine = Pens[SHADOWPEN];
Shadow = Pens[SHINEPEN];
Txt = Pens[FILLTEXTPEN];
Fill = Pens[FILLPEN];
}
else
{
Shine = Pens[SHINEPEN];
Shadow = Pens[SHADOWPEN];
Txt = Pens[TEXTPEN];
Fill = Pens[BACKGROUNDPEN];
}
SetDrMd(RPort,JAM1);
SetAPen(RPort,Fill);
RectFill(RPort,Left + 2,Top + 1,Left + Width - 3,Top + Height - 2);
SetAPen(RPort,Shine);
Move(RPort,Left + 1,Top + 1);
Draw(RPort,Left + 1,Top + Height - 2);
Draw(RPort,Left,Top + Height - 1);
Draw(RPort,Left,Top);
Draw(RPort,Left + Width - 2,Top);
SetAPen(RPort,Shadow);
Move(RPort,Left + Width - 2,Top + Height - 2);
Draw(RPort,Left + Width - 2,Top + 1);
Draw(RPort,Left + Width - 1,Top);
Draw(RPort,Left + Width - 1,Top + Height - 1);
Draw(RPort,Left + 1,Top + Height - 1);
SetAPen(RPort,Pens[SHADOWPEN]);
Move(RPort,Left + Info->MarkLeft,Top + 2);
Draw(RPort,Left + Info->MarkLeft,Top + Height - 3);
SetAPen(RPort,Pens[SHINEPEN]);
Move(RPort,Left + Info->MarkLeft + 1,Top + 2);
Draw(RPort,Left + Info->MarkLeft + 1,Top + Height - 3);
SetFont(RPort,Info->Font);
SetAPen(RPort,Txt);
DrawArrow(RPort,Left + 4,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,1);
Move(RPort,Left + Info->LabelLeft,Top + Info->LabelBase);
Text(RPort,Info->Labels[Info->Active],Info->ActiveLen);
/* // Intuition ghosts images all by itself
if(Disabled)
DrawDisabled(RPort,Left,Top,Width,Height,Pens);
*/
}
STATIC VOID __regargs
DrawOneBox(PopInfo *Info,UWORD Top,STRPTR Label)
{
struct RastPort *RPort;
LONG Len;
RPort = Info->Window->RPort;
if((Len = strlen(Label)) > Info->MaxLen)
Len = Info->MaxLen;
Move(RPort,6,Top + Info->LineBase);
Text(RPort,Label,Len);
}
STATIC VOID __regargs
DrawOneGlyph(PopInfo *Info,UWORD Top,WORD Dir,UWORD *Pens)
{
struct RastPort *RPort;
RPort = Info->Window->RPort;
if(Pens)
{
SetAPen(RPort,Info->MenuBack);
RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
SetAPen(RPort,Info->MenuText);
}
DrawArrow(RPort,6,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,Dir);
}
STATIC VOID __regargs
BoxRender(PopInfo *Info,UWORD *Pens,LONG Active,BOOL FullRefresh,BOOL Highlight,WORD Dir)
{
struct RastPort *RPort = Info->Window->RPort;
if(FullRefresh)
{
LONG Index,Top,Width,Height;
SetAPen(RPort,Info->MenuBack);
SetDrMd(RPort,JAM1);
Width = Info->Window->Width;
Height = Info->Window->Height;
RectFill(RPort,2,1,Width - 3,Height - 2);
SetAPen(RPort,Info->MenuText);
Move(RPort,1,1);
Draw(RPort,1,Height - 2);
Draw(RPort,0,Height - 2);
Draw(RPort,0,0);
Draw(RPort,Width - 1,0);
Move(RPort,0,Height - 1);
Draw(RPort,Width - 1,Height - 1);
Draw(RPort,Width - 1,1);
Draw(RPort,Width - 2,1);
Draw(RPort,Width - 2,Height - 2);
Index = Info->TopMost;
Top = 2;
Height = Info->BoxHeight;
Info->Flags &= ~(PIF_ArrowUp | PIF_ArrowDown);
if(Info->TopMost > 0 && Active != Info->TopMost && Info->BoxLines > 2)
{
Info->Flags |= PIF_ArrowUp;
Index += 1;
Top += Info->SingleHeight;
Height -= Info->SingleHeight;
}
if(Info->TopMost + Info->BoxLines < Info->NumLabels && Active != Info->TopMost + Info->BoxLines - 1 && Info->BoxLines > 2)
{
Info->Flags |= PIF_ArrowDown;
Height -= Info->SingleHeight;
}
for( ; Index < Info->NumLabels && Height > 0 ; Index++, Top += Info->SingleHeight, Height -= Info->SingleHeight)
{
if(Index == Active)
{
SetAPen(RPort,Info->MenuBackSelect);
RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
SetAPen(RPort,Info->MenuTextSelect);
DrawOneBox(Info,Top,Info->Labels[Index]);
SetAPen(RPort,Info->MenuText);
}
else
DrawOneBox(Info,Top,Info->Labels[Index]);
}
if(Info->Flags & PIF_ArrowUp)
DrawOneGlyph(Info,2,-1,NULL);
if(Info->Flags & PIF_ArrowDown)
DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,NULL);
Info->LastDrawn = 2 + (Active - Info->TopMost) * Info->SingleHeight;
Info->LastLabelDrawn = Info->Labels[Active];
}
else
{
if(Info->LastLabelDrawn)
{
LONG Top = Info->LastDrawn;
SetDrMd(RPort,JAM1);
SetAPen(RPort,Info->MenuBack);
RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
SetAPen(RPort,Info->MenuText);
DrawOneBox(Info,Top,Info->LastLabelDrawn);
}
Info->LastDrawn = -1;
Info->LastLabelDrawn = NULL;
if(Active >= 0)
{
LONG Top,NewActive;
NewActive = Active - Info->TopMost;
Top = 2 + NewActive * Info->SingleHeight;
if(Top >= 2 && Top < Info->BoxHeight + 2)
{
UWORD Pen;
if(Dir != 0)
Highlight = FALSE;
if(Highlight)
{
Pen = Info->MenuBackSelect;
Info->LastDrawn = Top;
Info->LastLabelDrawn = Info->Labels[Active];
}
else
Pen = Info->MenuBack;
SetDrMd(RPort,JAM1);
SetAPen(RPort,Pen);
RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
if(Highlight)
Pen = Info->MenuTextSelect;
else
Pen = Info->MenuText;
SetAPen(RPort,Pen);
if(Dir == 0)
DrawOneBox(Info,Top,Info->Labels[Active]);
else
DrawOneGlyph(Info,Top,Dir,NULL);
}
}
}
}
STATIC ULONG __regargs
InputMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
ULONG Result = GMR_MEACTIVE;
BOOL Done = FALSE;
if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
{
UWORD Code = InputInfo->gpi_IEvent->ie_Code;
if(Code == MENUDOWN)
{
Result = GMR_NOREUSE;
Done = TRUE;
Info->Active = Info->InitialActive;
}
else
{
if(Code == SELECTUP)
{
Done = TRUE;
if(Info->Active < 0)
{
Result = GMR_NOREUSE;
Info->Active = Info->InitialActive;
}
else
{
LONG Len;
Result = GMR_REUSE | GMR_VERIFY;
if(Info->Flags & PIF_SingleActive)
{
UWORD Width,Height;
WORD x,y;
x = InputInfo->gpi_Mouse . X;
y = InputInfo->gpi_Mouse . Y;
Width = gadget->Width;
Height = gadget->Height;
if(x >= 0 && y >= 0 && x < Width && y < Height)
{
if(InputInfo->gpi_IEvent->ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
Info->Active--;
else
Info->Active++;
if(Info->Active >= Info->NumLabels)
Info->Active = 0;
else
{
if(Info->Active < 0)
Info->Active = Info->NumLabels - 1;
}
}
else
{
Result = GMR_NOREUSE;
Info->Active = Info->InitialActive;
}
}
Len = strlen(Info->Labels[Info->Active]);
if(Len > Info->MaxLen)
Len = Info->MaxLen;
Info->ActiveLen = Len;
*InputInfo->gpi_Termination = Info->Active;
}
}
else
{
if(Info->Flags & PIF_SingleActive)
{
UWORD Left,Top,Width,Height;
WORD x,y;
x = InputInfo->gpi_Mouse . X;
y = InputInfo->gpi_Mouse . Y;
Left = gadget->LeftEdge;
Top = gadget->TopEdge;
Width = gadget->Width;
Height = gadget->Height;
if(x < 0 || y < 0 || x >= Width || y >= Height)
{
if(gadget->Flags & GFLG_SELECTED)
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
{
DrawContainer(RPort,Left,Top,Width,Height,InputInfo->gpi_GInfo,Info,FALSE,FALSE);
gadget->Flags &= ~GFLG_SELECTED;
ReleaseGIRPort(RPort);
}
}
}
else
{
if(!(gadget->Flags & GFLG_SELECTED))
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
{
DrawContainer(RPort,Left,Top,Width,Height,InputInfo->gpi_GInfo,Info,TRUE,FALSE);
gadget->Flags |= GFLG_SELECTED;
ReleaseGIRPort(RPort);
}
}
}
}
}
}
if(Done)
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
{
DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,InputInfo->gpi_GInfo,Info,FALSE,FALSE);
ReleaseGIRPort(RPort);
}
if(Info->Window)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
Info->Flags &= ~PIF_SingleActive;
}
}
if(!Done && Info->Window)
{
LONG NewActive = 0;
WORD x,y;
WORD Dir = 0;
UWORD From,To;
x = InputInfo->gpi_GInfo->gi_Screen->MouseX - Info->BoxLeft;
y = InputInfo->gpi_GInfo->gi_Screen->MouseY - Info->BoxTop;
if(x < 0 || x >= Info->BoxWidth)
NewActive = -1;
else
{
UWORD Margin;
if(Info->Flags & (PIF_ArrowUp | PIF_ArrowDown))
Margin = Info->SingleHeight;
else
Margin = (Info->SingleHeight + 3) / 4;
// Scroll up?
if(y < Margin)
{
if(y < 0)
NewActive = -1;
else
{
// Topmost line concealed?
if(Info->TopMost > 0)
{
Info->TopMost--;
From = 2;
To = 2 + Info->BoxHeight - 1;
Dir = -Info->SingleHeight;
}
}
}
else
{
LONG Last;
Last = Info->NumLabels - Info->TopMost;
if(Last < Info->BoxLines)
Last = Last * Info->SingleHeight;
else
Last = Info->BoxHeight;
// Scroll up?
if(y >= Last - Margin)
{
if(y >= Last)
NewActive = -1;
else
{
// Last line concealed?
if(Info->TopMost + Info->BoxLines < Info->NumLabels)
{
Info->TopMost++;
From = 2;
To = 2 + Info->BoxHeight - 1;
Dir = Info->SingleHeight;
}
}
}
}
if(NewActive != -1)
{
NewActive = Info->TopMost + y / Info->SingleHeight;
if(NewActive < 0)
NewActive = 0;
else
{
if(NewActive >= Info->NumLabels)
NewActive = Info->NumLabels - 1;
}
}
}
if(NewActive != Info->Active || Dir != 0)
{
WORD Arrow;
UWORD *Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
if(Dir != 0)
{
struct RastPort *RPort = Info->Window->RPort;
Arrow = (NewActive == Info->TopMost) ? -1 : 1;
BoxRender(Info,Pens,-1,FALSE,FALSE,0);
if(Info->Flags & PIF_ArrowUp)
From += Info->SingleHeight;
if(Info->Flags & PIF_ArrowDown)
To -= Info->SingleHeight;
SetBPen(RPort,Pens[BACKGROUNDPEN]);
ScrollRaster(RPort,0,Dir,4,From,4 + Info->BoxWidth - 1,To);
if(Dir < 0)
BoxRender(Info,Pens,Info->TopMost + 1,FALSE,FALSE,0);
else
BoxRender(Info,Pens,Info->TopMost + Info->BoxLines - 2,FALSE,FALSE,0);
if(!Info->TopMost || Info->BoxLines < 3)
{
Info->Flags &= ~PIF_ArrowUp;
Arrow = 0;
}
else
{
if(!(Info->Flags & PIF_ArrowUp))
{
Info->Flags |= PIF_ArrowUp;
DrawOneGlyph(Info,2,-1,Pens);
}
}
if(Info->TopMost + Info->BoxLines >= Info->NumLabels || Info->BoxLines < 3)
{
Info->Flags &= ~PIF_ArrowDown;
Arrow = 0;
}
else
{
if(!(Info->Flags & PIF_ArrowDown))
{
Info->Flags |= PIF_ArrowDown;
DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,Pens);
}
}
}
else
Arrow = 0;
Info->Active = NewActive;
BoxRender(Info,Pens,NewActive,FALSE,TRUE,Arrow);
}
}
return(Result);
}
STATIC ULONG __regargs
SetMethod(struct IClass *class,struct Gadget *gadget,struct opSet *SetInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
struct TagItem *This;
LONG NewActive;
STRPTR *NewLabels;
ULONG Result;
UWORD Flags = gadget -> Flags;
BOOL NeedRefresh = FALSE;
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
Result = DoSuperMethodA(class,(Object *)gadget,(Msg)SetInfo);
if(This = FindTagItem(GA_Disabled,SetInfo->ops_AttrList))
{
if(This -> ti_Data && !(Flags & GFLG_DISABLED) || !This -> ti_Data && (Flags & GFLG_DISABLED))
NeedRefresh = TRUE;
}
NewLabels = (STRPTR *)GetTagData(PIA_Labels,NULL,SetInfo->ops_AttrList);
if(This = FindTagItem(PIA_Active,SetInfo->ops_AttrList))
{
LONG NumLabels = Info->NumLabels;
if(NewLabels)
for(NumLabels = 0 ; NewLabels[NumLabels] ; NumLabels++);
NewActive = (LONG)This->ti_Data;
if(NewActive < 0)
NewActive = 0;
else
{
if(NewActive >= NumLabels)
NewActive = NumLabels - 1;
}
}
else
NewActive = -1;
if((NewActive != Info->Active && NewActive != -1) || NewLabels)
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
{
UWORD Left,Top,Width;
LONG Len;
STRPTR *Labels;
LONG NumLabels,MaxLen,ActiveLen;
UWORD *Pens;
if(NewLabels)
{
struct TextExtent Extent;
for(NumLabels = MaxLen = 0 ; NewLabels[NumLabels] ; NumLabels++)
{
Len = TextFit(RPort,NewLabels[NumLabels],strlen(NewLabels[NumLabels]),&Extent,NULL,1,Info->MaxWidth,32767);
if(Len > MaxLen)
MaxLen = Len;
}
Labels = NewLabels;
}
else
{
Labels = Info->Labels;
NumLabels = Info->NumLabels;
MaxLen = Info->MaxLen;
}
if(NewActive == -1)
NewActive = Info->Active;
if(NewActive >= NumLabels)
NewActive = NumLabels - 1;
Pens = SetInfo->ops_GInfo->gi_DrInfo->dri_Pens;
Left = gadget -> LeftEdge;
Top = gadget -> TopEdge;
SetFont(RPort,Info->Font);
Len = strlen(Labels[NewActive]);
if(Len > MaxLen)
Len = MaxLen;
ActiveLen = Len;
Width = TextLength(RPort,Labels[NewActive],ActiveLen);
SetDrMd(RPort,JAM2);
if(Width < Info->MaxWidth)
{
SetAPen(RPort,Pens[BACKGROUNDPEN]);
RectFill(RPort,Left + Info->LabelLeft + Width,Top + Info->LabelTop,Left + Info->LabelLeft + Info->MaxWidth - 1,Top + Info->LabelTop + RPort->TxHeight - 1);
}
SetAPen(RPort,Pens[TEXTPEN]);
SetBPen(RPort,Pens[BACKGROUNDPEN]);
Move(RPort,Left + Info->LabelLeft,Top + Info->LabelBase);
Text(RPort,Labels[NewActive],ActiveLen);
Info->Active = NewActive;
Info->ActiveLen = ActiveLen;
if(NewLabels)
{
Info->Labels = Labels;
Info->NumLabels = NumLabels;
Info->MaxLen = MaxLen;
}
/* // Intuition ghosts images all by itself
if(((struct Gadget *)object) -> Flags & GFLG_DISABLED)
{
UWORD Height;
Width = ((struct Gadget *)object) -> Width;
Height = ((struct Gadget *)object) -> Height;
DrawDisabled(RPort,Left,Top,Width,Height,Pens);
}
*/
NeedRefresh = FALSE;
ReleaseGIRPort(RPort);
}
}
if(!(gadget -> Flags & GFLG_DISABLED) && (This = FindTagItem(PIA_Highlight,SetInfo->ops_AttrList)))
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
{
DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,SetInfo->ops_GInfo,Info,This->ti_Data,FALSE);
NeedRefresh = FALSE;
ReleaseGIRPort(RPort);
}
}
if(NeedRefresh)
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
{
DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,SetInfo->ops_GInfo,Info,FALSE,gadget -> Flags & GFLG_DISABLED);
ReleaseGIRPort(RPort);
}
}
return(Result);
}
STATIC ULONG __regargs
RenderMethod(struct IClass *class,struct Gadget *gadget,struct gpRender *RenderInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
DrawContainer(RenderInfo->gpr_RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,RenderInfo->gpr_GInfo,Info,gadget->Flags & GFLG_SELECTED,gadget->Flags & GFLG_DISABLED);
return(TRUE);
}
STATIC ULONG __regargs
DisposeMethod(struct IClass *class,Object *object,Msg msg)
{
PopInfo *Info = INST_DATA(class,object);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
if(Info->Font)
{
CloseFont(Info->Font);
Info->Font = NULL;
}
if(Info->Window)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
return(DoSuperMethodA(class,object,msg));
}
STATIC ULONG __regargs
NewMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
{
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
if(object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo))
{
PopInfo *Info = INST_DATA(class,object);
struct TagItem *Item,*TagList = SetInfo -> ops_AttrList;
struct TextAttr *Font;
LONG Width,Height;
Width = Height = 0;
Font = NULL;
memset(Info,0,sizeof(PopInfo));
while(Item = NextTagItem(&TagList))
{
switch(Item->ti_Tag)
{
case GA_Width:
Width = Item->ti_Data;
break;
case GA_Height:
Height = Item->ti_Data;
break;
case PIA_Labels:
Info->Labels = (STRPTR *)Item->ti_Data;
break;
case PIA_Active:
Info->Active = (LONG)Item->ti_Data;
break;
case PIA_Font:
Font = (struct TextAttr *)Item->ti_Data;
break;
}
}
if(Font && Info->Labels && Width && Height)
{
while(Info->Labels[Info->NumLabels])
Info->NumLabels++;
if(Info->NumLabels)
{
if(Info->Font = OpenFont(Font))
{
struct RastPort __aligned RPort;
if(Info->Active < 0)
Info->Active = 0;
else
{
if(Info->Active >= Info->NumLabels)
Info->Active = Info->NumLabels - 1;
}
InitRastPort(&RPort);
SetFont(&RPort,Info->Font);
Info->ArrowWidth = (TextLength(&RPort,"M",1) & ~1) + 1;
Info->ArrowHeight = (2 * RPort.TxHeight) / 3;
Info->ArrowTop = (Height - Info->ArrowHeight) / 2;
Info->MarkLeft = 4 + Info->ArrowWidth + 2;
Info->MarkWidth = Info->MarkLeft + 4;
Info->PopLeft = Info->MarkWidth - 6;
Info->PopWidth = Width - Info->PopLeft;
Info->LabelTop = (Height - RPort.TxHeight) / 2;
Info->LabelLeft = Info->MarkWidth;
Info->LabelBase = Info->LabelTop + RPort.TxBaseline;
Width -= 6 + Info->MarkWidth + 6;
Height -= 2 + RPort.TxHeight + 2;
if(Width > 0 && Height >= 0)
{
struct TextExtent Extent;
LONG i,Len,MaxLen;
for(i = MaxLen = 0 ; i < Info->NumLabels ; i++)
{
Len = TextFit(&RPort,Info->Labels[i],strlen(Info->Labels[i]),&Extent,NULL,1,Width,32767);
if(Len > MaxLen)
MaxLen = Len;
}
if(MaxLen)
{
Len = strlen(Info->Labels[Info->Active]);
if(Len > MaxLen)
Len = MaxLen;
Info->ActiveLen = Len;
Info->MaxLen = MaxLen;
Info->MaxWidth = Width;
return((ULONG)object);
}
}
CloseFont(Info->Font);
Info->Font = NULL;
}
}
}
CoerceMethod(class,object,OM_DISPOSE);
}
return(0);
}
STATIC ULONG __regargs
ActiveMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
struct RastPort *RPort;
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
{
LONG Left,Top;
Left = gadget->LeftEdge;
Top = gadget->TopEdge;
Info->Window = NULL;
if(Info->NumLabels > 2 && InputInfo->gpi_Mouse.X >= Info->MarkLeft)
{
UWORD SingleHeight,ScreenHeight,Width,Height;
Info->Flags &= ~PIF_SingleActive;
Info->Window = NULL;
SetFont(RPort,Info->Font);
SingleHeight = gadget->Height;
ScreenHeight = InputInfo->gpi_GInfo->gi_Screen->Height;
Info->LineTop = (SingleHeight - RPort->TxHeight) / 2;
Info->LineBase = Info->LineTop + RPort->TxBaseline;
Width = Info->PopWidth;
Height = 2 + SingleHeight * Info->NumLabels + 2;
while(Height > SingleHeight && Height > ScreenHeight)
Height -= SingleHeight;
if(Height > SingleHeight)
{
LONG LeftEdge,TopEdge,TopMost;
LeftEdge = InputInfo->gpi_GInfo->gi_Window->LeftEdge + Left + Info->PopLeft;
TopEdge = InputInfo->gpi_GInfo->gi_Window->TopEdge + Top + Info->LabelTop - (2 + Info->LineTop + Info->Active * SingleHeight);
TopMost = 0;
while(TopEdge < 0 && TopMost < Info->NumLabels)
{
TopEdge += SingleHeight;
TopMost += 1;
}
if(TopEdge >= 0 && TopMost < Info->NumLabels)
{
while(Height > SingleHeight && TopEdge + Height > ScreenHeight)
Height -= SingleHeight;
if(Height > SingleHeight && TopEdge + Height <= ScreenHeight)
{
ReleaseGIRPort(RPort);
if(Info->Window = OpenWindowTags(NULL,
WA_Left, LeftEdge,
WA_Top, TopEdge,
WA_Width, Width,
WA_Height, Height,
WA_SimpleRefresh, TRUE,
WA_NoCareRefresh, TRUE,
WA_AutoAdjust, FALSE,
WA_CustomScreen, InputInfo->gpi_GInfo->gi_Screen,
WA_Borderless, TRUE,
V39 ? WA_BackFill : TAG_IGNORE,LAYERS_NOBACKFILL,
TAG_DONE))
{
UWORD *Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
Info->TopMost = TopMost;
Info->BoxLeft = LeftEdge + 4;
Info->BoxTop = TopEdge + 2;
Info->BoxWidth = Width - 8;
Info->BoxHeight = Height - 4;
Info->BoxLines = Info->BoxHeight / SingleHeight;
Info->SingleWidth = Width - 8;
Info->SingleHeight = SingleHeight;
if(V39)
{
STATIC BYTE RenderPens[] =
{
BACKGROUNDPEN,
FILLPEN,
TEXTPEN,
FILLTEXTPEN,
SHADOWPEN,
SHINEPEN,
BARDETAILPEN,
BARBLOCKPEN
-1
};
UWORD i,Pen,Max = 0;
Info->MenuText = Pens[BARDETAILPEN];
Info->MenuBack = Pens[BARBLOCKPEN];
Info->MenuTextSelect = Pens[BARBLOCKPEN];
Info->MenuBackSelect = Pens[BARDETAILPEN];
for(i = 0 ; RenderPens[i] != -1 ; i++)
{
if((Pen = Pens[RenderPens[i]]) > Max)
Max = Pen;
}
SetMaxPen(Info->Window->RPort,Max);
}
else
{
Info->MenuText = Pens[DETAILPEN];
Info->MenuBack = Pens[BLOCKPEN];
Info->MenuTextSelect = ~Pens[DETAILPEN];
Info->MenuBackSelect = ~Pens[BLOCKPEN];
}
SetFont(Info->Window->RPort,Info->Font);
}
if(!(RPort = ObtainGIRPort(InputInfo->gpi_GInfo)))
{
if(Info->Window)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
}
}
}
}
}
if(!Info->Window)
Info->Flags |= PIF_SingleActive;
if(((Info->Flags & PIF_SingleActive) || Info->Window) && RPort)
{
UWORD Width,Height;
Info->InitialActive = Info->Active;
Width = gadget->Width;
Height = gadget->Height;
DrawContainer(RPort,Left,Top,Width,Height,InputInfo->gpi_GInfo,Info,TRUE,FALSE);
ReleaseGIRPort(RPort);
if(Info->Window)
BoxRender(Info,InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens,Info->Active,TRUE,TRUE,0);
return(GMR_MEACTIVE);
}
if(RPort)
ReleaseGIRPort(RPort);
}
return(GMR_NOREUSE);
}
STATIC ULONG __regargs
InactiveMethod(struct IClass *class,struct Gadget *gadget,struct gpGoInactive *InactiveInfo)
{
PopInfo *Info = INST_DATA(class,gadget);
DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
if(Info->Window || (Info->Flags & PIF_SingleActive))
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
{
DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,InactiveInfo->gpgi_GInfo,Info,FALSE,FALSE);
ReleaseGIRPort(RPort);
}
if(Info->Window)
{
CloseWindow(Info->Window);
Info->Window = NULL;
}
Info->Flags &= ~PIF_SingleActive;
}
return(0);
}
ULONG __saveds __asm
LTP_PopupClassDispatcher(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
{
switch(msg->MethodID)
{
case OM_NEW:
return(NewMethod(class,object,(struct opSet *)msg));
case OM_UPDATE:
case OM_SET:
return(SetMethod(class,(struct Gadget *)object,(struct opSet *)msg));
case OM_DISPOSE:
return(DisposeMethod(class,object,msg));
case GM_RENDER:
return(RenderMethod(class,(struct Gadget *)object,(struct gpRender *)msg));
case GM_HITTEST:
return(GMR_GADGETHIT);
case GM_GOINACTIVE:
return(InactiveMethod(class,(struct Gadget *)object,(struct gpGoInactive *)msg));
case GM_GOACTIVE:
return(ActiveMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
case GM_HANDLEINPUT:
return(InputMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
default:
return(DoSuperMethodA(class,object,msg));
}
}
#endif // defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)